package com.ssm.basis;

import com.ssm.basis.service.util.SpringHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;

import java.time.Duration;

/**
 * 在 spring.factories 中配置，不可被 Application 再次扫描到
 * https://blog.csdn.net/f641385712/article/details/89231174
 * https://blog.csdn.net/f641385712/article/details/105596178
 *
 * @see ApplicationContextInitializer
 * https://blog.csdn.net/f641385712/article/details/92709404
 * * 生命周期事件
 * https://blog.csdn.net/f641385712/article/details/105762050
 */
@Slf4j
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigureBefore(DispatcherServletAutoConfiguration.class) // 在 DispatcherServletAutoConfiguration 之前执行此配置
public class ApplicationRunListener implements SpringApplicationRunListener {
    public ApplicationRunListener(SpringApplication application, String[] args) {
        log.debug("MyApplicationRunListener Constructor");
    }

    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        log.debug("MyApplicationRunListener-starting...");
        log.debug("在 run() 方法开始执行时，该方法就立即被调用，可用于在初始化最早期时做一些工作");
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        log.debug("MyApplicationRunListener-environmentPrepared...");
        log.debug("当 environment 构建完成，ApplicationContext 创建之前，该方法被调用");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        log.debug("MyApplicationRunListener-contextPrepared...");
        log.debug("当 ApplicationContext 构建完成时，该方法被调用");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        log.debug("MyApplicationRunListener-contextLoaded...");
        log.debug("在 ApplicationContext 完成加载，但没有被刷新前，该方法被调用");
    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        log.debug("MyApplicationRunListener-started...");
        log.debug("在 ApplicationContext 刷新并启动后，CommandLineRunners 和 ApplicationRunner 未被调用前，该方法被调用");
    }

    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        log.debug("MyApplicationRunListener-running...");
        log.debug("在 run() 方法执行完成前该方法被调用");
        SpringHelper.setApplicationContext(context);
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        log.debug("MyApplicationRunListener-failed...");
        log.debug("当应用运行出错时该方法被调用");
    }
}